package com.mini.mybatis.mybatisministep09.executor;

import com.mini.mybatis.mybatisministep09.mapping.BoundSql;
import com.mini.mybatis.mybatisministep09.mapping.MappedStatement;
import com.mini.mybatis.mybatisministep09.sqlsession.ResultHandler;
import com.mini.mybatis.mybatisministep09.sqlsession.configuration.Configuration;
import com.mini.mybatis.mybatisministep09.transaction.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.List;

/**
 * 执行器抽象基类，定义步骤模板
 */
public abstract class BaseExecutor implements Executor{

    private Logger logger = LoggerFactory.getLogger(BaseExecutor.class);

    protected Configuration configuration;

    protected Transaction transaction;

    protected Executor wrapper;

    private boolean closed = false;


    public BaseExecutor(Configuration configuration, Transaction transaction) {
        this.configuration = configuration;
        this.transaction = transaction;
        this.wrapper = this;
    }

    @Override
    public <E> List<E> query(MappedStatement ms, Object parameter, ResultHandler resultHandler, BoundSql boundSql) {
        if (closed){
            throw new RuntimeException("Executor was close!");
        }
        return doQuery(ms,parameter,resultHandler,boundSql);
    }

    protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, ResultHandler resultHandler, BoundSql boundSql);

    @Override
    public Transaction getTransaction() {
        if (closed){
            throw new RuntimeException("Executor was close!");
        }
        return transaction;
    }

    @Override
    public void commit(boolean require) throws SQLException {
        if (closed){
            throw new RuntimeException("Executor was close!");
        }
        if (require){
            transaction.commit();
        }
    }

    @Override
    public void rollback(boolean require) throws SQLException {
        if (!closed){
            if (require){
                transaction.rollback();
            }
        }
    }

    @Override
    public void close(boolean forceRollback) {
        try {
            try {
                rollback(forceRollback);
            } finally {
                transaction.close();
            }
        } catch (SQLException e) {
            logger.warn("Unexpected exception on closing transaction.  Cause: " + e);
        } finally {
            transaction = null;
            closed = true;
        }
    }
}
